
#include "CondNotice.h"
#include "List.h"
#include <ArduinoJson.h>
#include "SensorData.h"
#include "global.h"
#include "httpfunc.h"
#include "SimpleMap.h"

List<CondNotice> *condNotice;

List<ReqNotice> reqNoticeList;

SimpleMap<String, ReqNotice> *latestNoticeMap;

RTC_DATA_ATTR ReqNotice latestIdlePumpNotice;

RTC_DATA_ATTR ReqNotice latestLackWaterNotice;

class CN
{

public:
    String name;
    long epoch;
    bool isEmpty(){
        return name.isEmpty();
    }
    CN(/* args */){

    }
    ~CN(){

    }
};

 
RTC_DATA_ATTR CN cn[10];


  long  getTriggleCNEpoch(String name){
    for (size_t i = 0; i < 10; i++)
    {
         if(cn[i].name.equals(name)){
            return cn[i].epoch;
         }
    }
    return 0;
}

bool putTriggleCNEpoch(String name,long epoch){

    int index=0;
    for (size_t i = 0; i < 10; i++)
    {
        if(cn[i].name.equals(name)){
            cn[i].epoch = epoch;
            return true;
        }  
         index++;
    }
    if(index==10){
        for (size_t i = 0; i < 10; i++)
        {
            if(cn[i].isEmpty()){
                cn[i].name = name;
                cn[i].epoch = epoch;
                return true;
            }
        }
    }
    return false;
}




  int   CondNotice::isNeedTriggle()
    {
        if (this->frequency < 0)
        { // 永不触发
            return -1;
        }

        if (getGlobalLocalConfig()->getTypeConfig()->getRunMode() == 1)
        {
            if (this->frequency == 0)
            { // 触发一次
                if (this->lastTime == 0)
                {
                    this->lastTime = getRtcTime().getEpoch();
                    return 0;
                }
                return -2;
            }

            // 间隔多次触发，从未触发过
            if (this->lastTime == 0)
            {
                this->lastTime = getRtcTime().getEpoch();
                return 0;
            }
            long interval = this->frequency * 60;
            long d = getRtcTime().getEpoch() - (this->lastTime + interval);
           // printStr("d==", d);
            if (d == 0)
            {
                this->lastTime = getRtcTime().getEpoch();
                return 0;
            }
        }
        else
        {
            long latestTriggleEpoch =  getTriggleCNEpoch(this->name);
            if (this->frequency == 0)
            { // 触发一次
                if (latestTriggleEpoch == 0)
                {
                    putTriggleCNEpoch(this->name,getRtcTime().getEpoch());
                    return 0;
                }
                return -2;
            }
            // 间隔多次触发，从未触发过
            if (latestTriggleEpoch == 0)
            {
                 putTriggleCNEpoch(this->name,getRtcTime().getEpoch());
                return 0;
            }
            //todo
            long interval = this->frequency * 60+getTimerWakeup();
            
            long d = getRtcTime().getEpoch() - ( latestTriggleEpoch+ interval);
          //  printStr("d==",d);
            if (d >= 0 && d < interval +60)
            {
                putTriggleCNEpoch(this->name,getRtcTime().getEpoch());
                return 0;
            }
        }

        return -3;
    }

    int  CondNotice::getCount()
    {
        return count;
    }

    //bool  CondNotice::isTriggle();

    String  CondNotice::getName()
    {
        return name;
    }

    String  CondNotice::getNoticeId()
    {
        return noticeId;
    }

    void  CondNotice::setName(String name)
    {
        this->name = name;
    }

    void  CondNotice::setNoticeId(String id)
    {
        this->noticeId = id;
    }

    void  CondNotice::print()
    {
        // printStr("name", name);
        // printStr("lastTime", lastTime);
        // printStr("frequency", frequency);
        // printStr("disable", disable);
        for (size_t i = 0; i < count; i++)
        {
            conds[i].print();
        }
    }
    void  CondNotice::addCond(Conds cond)
    {
        if (count >= 5)
        {
            return;
        }
        conds[count] = cond;
        count++;
    }

    Conds  CondNotice::getCond(int index)
    {
        return conds[index];
    }

    Conds * CondNotice::getCondById(String id)
    {
        for (size_t i = 0; i < count; i++)
        {
            if (conds[i].id.equals(id))
            {
                return &conds[i];
            }
        }
        return nullptr;
    }

    void  CondNotice::setFrequency(int frequency)
    {
        this->frequency = frequency;
    }

    void  CondNotice::setDisable(bool b)
    {
        this->disable = b;
    }

    bool  CondNotice::getDisable()
    {
        return this->disable;
    }











bool parseCondNotice(String condNoticeJSON)
{

    if (isStringEmpty(condNoticeJSON))
    {
        printStr("通知数据为空!");
        return false;
    }

    if (condNotice != nullptr)
    {
        delete condNotice;
    }
    condNotice = new List<CondNotice>();
    JsonDocument doc;
    DeserializationError error = deserializeJson(doc, condNoticeJSON);
    if (error)
    {
        Serial.print(F("deserializeJson() failed: "));
        Serial.println(error.f_str());
        return false;
    }
    JsonArray arr = doc.as<JsonArray>();
    // 遍历数组并打印每个元素
    for (size_t i = 0; i < arr.size(); i++)
    {
        // Serial.print(arr[i]);

        CondNotice cn;
        int frequency = arr[i]["frequency"];
        bool disable = arr[i]["disable"];
        String noticeId = arr[i]["noticeId"];
        String name = arr[i]["name"];
        cn.setFrequency(frequency);
        cn.setDisable(disable);
        cn.setNoticeId(noticeId);
        cn.setName(name);

        JsonArray conds = arr[i]["conds"].as<JsonArray>();
        for (size_t j = 0; j < conds.size(); j++)
        {
            Conds cds;
            String id = conds[j]["id"];
            String logic = conds[j]["logic"];
            String sensorValue = conds[j]["sensorValue"];
            String name = conds[j]["name"];
            String unit = conds[j]["unit"];

            cds.id = id;
            cds.logic = logic;
            cds.sensorValue = sensorValue;
            cds.name = name;
            cds.unit = unit;

            cn.addCond(cds);
        }
        condNotice->add(cn);
    }

    return true;
}

void printCondNotice()
{
    for (size_t i = 0; i < condNotice->getSize(); i++)
    {
    }
}

void checkSendNotify()
{
    if (getCondNoticeList() == nullptr)
    {
        return;
    }
    getCondNoticeList()->forEach([](CondNotice &value)
                                 {
           // printStr(value.getName());
            bool b = value.isTriggle();
          //  printStr("isTriggle",b);
          
            if(b){
                //value.print();
                int ret =   value.isNeedTriggle();
                if(ret!=0){
                   // printStr("ret",ret);
                    return;
                }
               
               // printStr(value.getName());
                ReqNotice req;
                req.setDeviceId(getEspId());
                req.setNoticeId(value.getNoticeId());
                String msg;
                for (size_t i = 0; i < value.getCount(); i++)
                {
                     msg += value.getCond(i).toString()+"\n";
                }

                
                
                req.setMsg(msg);
                
                req.setType("2");
                req.setEpoch(getRtcTime().getEpoch());
                addNotice(req);
            } });
}

// 读取传感器的值
bool CondNotice::isTriggle()
{
    for (size_t i = 0; i < count; i++)
    {
        Conds *c = &conds[i];
        float value;
        bool b = getSensorValue(c->id, value);
        if (!b)
        {
            printStr("没有此传感器", c->id);
            return false;
        }

       String name = getName() + String("--:");
      // printStr(name, value);

        bool b1 = c->isMeet(value);
        if (!b1)
        {
           // printStr("条件不满足", c->id);
            return false;
        }
        c->triggleValue = value;
      //  printStr("c->triggleValue",c->triggleValue);
    }
   // printStr("条件满足");
    return true;
}

List<CondNotice> *getCondNoticeList()
{

    return condNotice;
}

void checkNotice(String s)
{
    checkSendNotify();
}

void setupCondNotice()
{
    addGlobalTimerCallBack("cond_notice", checkNotice);
    initLatestNoticeMap();
}

void initLatestNoticeMap()
{
    if (latestNoticeMap == nullptr)
    {
        latestNoticeMap = new SimpleMap<String, ReqNotice>([](String &a, String &b) -> int
                                                           {
        if (a == b) return 0;
        if (a > b) return 1;
        /*if (a < b) */ return -1; });
    }
}

ReqNotice getLatestReqNotice(String name)
{

    if (latestNoticeMap != nullptr)
    {
        ReqNotice notice = latestNoticeMap->get(name);
        if (!notice.isEmpty())
        {
            return notice;
        }
    }

    ReqNotice notice = ReqNotice::getReqNotice(name);
    if (!notice.isEmpty())
    {
        putLatestReqNotice(notice);
    }

    return notice;
}

void putLatestReqNotice(ReqNotice notice)
{

    String name = notice.getName();
    if (notice.getName().length() > 12)
    {
        name = notice.getName().substring(0, 12);
    }
    latestNoticeMap->put(name, notice);
    notice.savePrefrence();
}

// 将消息添加到数组中，主程序会自动发送和删除
void addNotice(ReqNotice req)
{

    printStr("添加通知");
    long epoch = getRtcTime().getEpoch();
    req.setEpoch(epoch);
    ReqNotice latestNotice = getLatestReqNotice(req.getName());
    bool isEqual = req.equals(latestNotice);
    printStr("isEqual", isEqual);
    long epochInterval = req.getEpoch() - latestNotice.getEpoch();// 这里的epochInterval时间过长

    printStr("通知间隔时间", epochInterval);
    printStr("通知频率", req.getFrequecy() * 60);

    if (isEqual && epochInterval <= 5)
    {
        return;
    }

    //epochInterval <req.getFrequecy() * 60 这里不能为等于
    if (isEqual && epochInterval <req.getFrequecy() * 60)
    {
        return;
    }
    else
    {
        printStr("添加通知到列表");
        putLatestReqNotice(req);
        if(getEnv().equals("dev")){
            String msg =  req.getMsg();
            msg.concat("【开发】");
            req.setMsg(msg);
        }

        reqNoticeList.add(req);
    }
}

void addOverloadNotice()
{

    addNotice("水泵过载", "水泵过载，长时间过载使用可能导致设备损坏，请检查进水口或出水口是否阻塞", "", "1", 15);
}

void addPumpIdleNotice()
{
    addNotice("水泵空转", " 请检查是否缺水", "", "1", 15);
}

void addLackWaterNotice()
{
    addNotice("缺水通知", " 请检查水桶是否有水", "", "1", 15);
}

// 如果设备电量低通知存在不发送，不存在发送
void addLowPowerNotice(String time)
{
    return;
    ReqNotice notice = getLatestReqNotice("设备电量低");
    if (!notice.isEmpty())
    {
        return;
    }
    //  long time =  notice.getEpoch();
    //  long curTime = getRtcTime().getEpoch();

    String tip = String("设备电量低进入休眠模式,") + time + String("后唤醒");
    addNotice("设备电量低", tip, "lowpower_notice", "1", 0);
}

void addNotice(String name, String msg, String noticeId, String type, int frequency)
{
    ReqNotice notice;
    notice.setDeviceId(getEspId());
    notice.setName(name);
    notice.setFrequency(frequency);
    notice.setMsg(msg);
    notice.setType(type);
    notice.setNoticeId(noticeId);
    notice.setEpoch(getRtcTime().getEpoch());
    addNotice(notice);
}

void sendNotice()
{

    if (reqNoticeList.isEmpty())
    {
        return;
    }
    reqNoticeList.forEach([](ReqNotice &notice)
                          { sendNotice(notice); });

    reqNoticeList.clear();
}

//   ReqNotice  ReqNotice::getReqNotice(String key){

//     ReqNotice notice;

//     return notice;
//   }